.data
instruction:	
.word	0			
op:				
.word	0				
srcA:			
.word	0	
srcB:			
.word	0
dest:			
.word	0
pc:				
.word	0
mem:			
.word	0

.text
main:	
	call SuperGarbage
	halt

SuperGarbage:
	
	// %l0 = int pc
	// %l1 = int *mem
	
	st		%l0, pc
	st		%l1, mem
	
whileloop:

	// instruction->op		= %l1
	// instruction->srcA 	= %l2
	// instruction->srcB 	= %l3
	// instruction->dest	= %l4
	
	// struct inst *instruction = &(mem[pc]);
	add		%l0, %l1, %tmp
	st		%tmp, instruction
	
	// int op = instruction->op
	ld		[%tmp+0], %l1
	st		%l1, op
	
	// int srcA = instruction->srcA;
	ld		[%tmp+1], %l2						
	st		%l2, srcA		
	
	// int srcB = instruction->srcB;
	ld		[%tmp+2], %l3							
	st		%l3, srcB			
	
	// int dest = instruciton->dest;
	ld		[%tmp+3], %l4					
	st		%l4, dest				
	
	// pc = pc + 4
	add		%l0, 4, %l0							
	st		%l0, pc

///////////////////////////////////////////////////////////////////////////////

case0:
	mov		0, %tmp								
	bne		%l1, %tmp, case1				

	// mem[dest] = mem[srcA] - mem[srcB]; 		
	ld		mem, %l0		// mem				
	
	add		%l0, %l2, %l2	// &mem[srcA]		
	ld		[%l2], %l2		// mem[srcA]		
	
	add		%l0, %l3, %l3	// &mem[srcB]		
	ld		[%l3], %l3		// mem[srcB]		
	
	// mem[srcA] - mem[srcB]
	sub		%l2, %l3, %l3						
	
	add		%l0, %l4, %l4	// &mem[dest]		
	
	// mem[dest] = mem[srcA] - mem[srcB]		
	st		%l3, [%l4]							
	
	// break;
	ba 		whileloop		
	
///////////////////////////////////////////////////////////////////////////////
	
case1:
	mov		1, %tmp								
	bne		%l1, %tmp, case2					
	
	// mem[dest] = mem[srcA] >> 1;	
	ld		mem, %l0		// mem				
	add		%l0, %l2, %l2	// &mem[srcA]		
	ld		[%l2], %l2		// mem[srcA]		
	
	add		%l0, %l4, %l4	// &mem[dest]		
		
	srl		%l2, 1, %l2		// mem[srcA] >> 1	
	
	// mem[dest] = mem[srcA] >> 1
	st		%l2, [%l4]							
	
	// break;
	ba 		whileloop							
	
///////////////////////////////////////////////////////////////////////////////

case2:
	mov		2, %tmp								
	bne		%l1, %tmp, case3					
	
	// mem[dest] = ~(mem[srcA] | mem[srcB]);
	ld		mem, %l0		// mem				
	
	add		%l0, %l2, %l2	// &mem[srcA]		
	ld		[%l2], %l2		// mem[srcA]		
	
	add		%l0, %l3, %l3	// &mem[srcB]		
	ld		[%l3], %l3		// mem[srcB]		
	
	add		%l0, %l4, %l4	// &mem[dest]		
	
	// (mem[srcA] | mem[srcB])
	nor		%l2, %l3, %l3											
	
	// mem[dest] = ~(mem[srcA] | mem[srcB])
	st		%l3, [%l4]							
	
	// break;
	ba 		whileloop	

///////////////////////////////////////////////////////////////////////////////

case3:
	mov		3, %tmp								
	bne		%l1, %tmp, case4					
	
	ld		mem, %l0		// mem				
	
	add		%l0, %l2, %l2	// &mem[srcA]		
	ld		[%l2], %l2		// mem[srcA]		
	add		%l0, %l2, %l2	// &mem[mem[srcA]]	
	ld		[%l2], %l2		// mem[mem[srcA]]	
	
	add		%l0, %l3, %l3	// &mem[srcB]		
	ld		[%l3], %l3		// mem[srcB]		
	
	add		%l0, %l4, %l4	// &mem[dest]		
	
	swap	%l2, %l3, %l4						
	
	// break;
	ba 		whileloop						

///////////////////////////////////////////////////////////////////////////////

case4:
	mov		4, %tmp								
	bne		%l1, %tmp, case5				
	
	// in mem[dest], mem[srcA];
	ld		mem, %l0		// mem				
	
	add		%l0, %l2, %l2	// &mem[srcA]	
	ld		[%l2], %l2		// mem[srcA]	
	
	add		%l0, %l4, %l4	// &mem[dest]	
	
	// in mem[dest], mem[srcA]
	in		%l4, %l2						
	
	// break;
	ba 		whileloop						
	
///////////////////////////////////////////////////////////////////////////////

case5:
	mov		5, %tmp								
	bne		%l1, %tmp, case6					
	
	// out mem[srcA], mem[srcB];
	ld		mem, %l0		// mem				
	
	add		%l0, %l2, %l2	// &mem[srcA]
	ld		[%l2], %l2		// mem[srcA]
				
	add		%l0, %l3, %l3	// &mem[srcB]		
	ld		[%l3], %l3		// mem[srcB]		
	
	// out mem[srcA], mem[srcB]
	out		%l2, %l3							
	
	// break;
	ba 		whileloop							

///////////////////////////////////////////////////////////////////////////////


case6:
	mov		6, %tmp								// 18
	bne		%l1, %tmp, case7					// 19
	
	// mem[dest] = pc;
	ld		mem, %l0		// mem				
	add		%l0, %l4, %l4	// &mem[dest]		
	ld		pc, %tmp		// pc				
	
	st		%tmp, [%l4]							
	
	// if (mem[srcA] < 0)
	add		%l0, %l2, %l2	// &mem[srcA]		
	ld		[%l2], %l2		// mem[srcA]		
	
	mov		0, %tmp									
	bge		%l1, %tmp, ifExit					
	
	// pc = mem[srcB];		
	add		%l0, %l3, %l3	// &mem[srcB]		
	ld		[%l3], %l3		// mem[srcB]		
	st		%l3, pc			// pc = mem[srcB]	
	
ifExit:

	// break;
	ba 		whileloop	
	
///////////////////////////////////////////////////////////////////////////////

case7:
	// return pc
	ld		pc, %rv			
	halt			
	
	//return 

///////////////////////////////////////////////////////////////////////////////

